//@flow

import React, {PureComponent} from 'react'

import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'

import * as actions from './RefreshActions'
import RefreshInitState from './RefreshInitState'

const initState = new RefreshInitState()

function mapStateToProps(identifier) {
    return (state) => {
        return {
            isRefreshing: state.refreshAble.get(identifier) ? state.refreshAble.get(identifier).isRefreshing : initState.isRefreshing,
            data: state.refreshAble.get(identifier) ? state.refreshAble.get(identifier).data : initState.data,
            error: state.refreshAble.get(identifier) ? state.refreshAble.get(identifier).error : initState.error,
        }
    }
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators(actions, dispatch)
}

const defaultAdapter = (data) => data
const defaultInitData = null

export default function (identifier, adapter = defaultAdapter, initData = defaultInitData) {
    return (WrappedComponent) => {
        return connect(mapStateToProps(identifier), mapDispatchToProps)(
            class extends PureComponent {
                constructor() {
                    super(...arguments)
                }

                _fetchData = (asyncApi) => {
                    this.props.fetchDataIfNeeded(asyncApi, identifier)
                }

                _fetchDataCancle = () => {
                    this.props.fetchDataCancle(identifier)
                }

                componentWillUnmount = () => {
                    this._fetchDataCancle()
                }

                render() {
                    return (
                        <WrappedComponent
                            {...this.props}
                            isRefreshing = {this.props.isRefreshing}
                            fetchData = {this._fetchData}
                            fetchDataCancle = {this._fetchDataCancle}
                            data = {adapter ? adapter(this.props.data) : (this.props.data || initData)}
                            error = {this.props.error}
                        />
                    )
                }
            }
        )
    }
}